< previous page page_234 next page >

Page 234
Solution 24
Callback That String
The problem is in the callback parameter, which is defined to be ByVal As String. When a callback parameter is declared ByVal As String, the function expects to see a pointer to a BSTR string. Because it is passed ByVal, the function assumes that the BSTR is a copy of the original string. As such, it is the function's responsibility to free the string before it returns. Unfortunately, the pointer is not a BSTR at allit is a regular NULL-terminated C string, and an ANSI one to boot. Not only will Visual Basic interpret the string incorrectly, it will crash spectacularly as soon as it tries to free what it thinks is a BSTR.
The solution is to change the parameter to be ByVal As Long. That loads the parameter with a pointer to a NULL-terminated ANSI C string. The lstrlen function can be used to determine the length of the string, and the lstrcpy function can be used to copy the data as shown in the correct code that follows.
A standard module contains
' Locales Puzzle
' Copyright © 1998 by Desaware Inc. All Rights Reserved
Option Explicit

Public Declare Function EnumSystemLocales Lib "kernel32" Alias _
"EnumSystemLocalesA" (ByVal lpLocaleEnumProc As Long, ByVal dwFlags _
As Long) As Long

Public Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" _
(ByVal dest As String, ByVal source As Long) As Long
Public Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" _
(ByVal source As Long) As Long

Public Const LCID_INSTALLED = &H1 ' installed Locale ids
Public Function EnumLocalesProc(ByVal Locale As Long) As Long
   Dim LocaleName As String
   LocaleName = String$(lstrlen(Locale) + 1, Chr$(0))
   Call lstrcpy(LocaleName, Locale)
   Debug.Print LocaleName
   EnumLocalesProc = True
End Function

 
< previous page page_234 next page >